home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / ingres04.lzh / source / ovqp / string.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-05-30  |  25.8 KB  |  1,324 lines

  1. # include    <stdio.h>
  2. # include    <ingres.h>
  3. # include    <aux.h>
  4. # include    <symbol.h>
  5. # include    <tree.h>
  6. # include    "../decomp/globs.h"
  7. # include    <sccs.h>
  8. # include    <errors.h>
  9.  
  10. char        *need();
  11.  
  12. SCCSID(@(#)string.c    8.5    5/30/88)
  13.  
  14. /*
  15. **    This file contains the string
  16. **    manipulation routines
  17. */
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25. /*
  26. **    Concat takes the two character strings in
  27. **    s1 and s2 and concatenates them together
  28. **    into a new location.
  29. **
  30. **    trailing blanks are removed from the first symbol.
  31. **    The size of the concatenation equals the sum of
  32. **    the two original strings.
  33. */
  34.  
  35. concatsym(s1, s2)
  36. register SYMBOL    *s1, *s2;
  37. {
  38.     register char    *p;
  39.     int        size1, size2, i;
  40.     char        *px;
  41.  
  42. /*    size1 = size(s1);*/    /* compute size w/o trailing blanks */
  43.     size1 = s1->len & I1MASK;
  44.     if (size1 == 0 && s1->len != 0)
  45.         size1++;    /* don't allow string to be trunc to zero length */
  46.     size2 = s2->len & I1MASK;    /* size of second string remains the same */
  47.     i = (s1->len & I1MASK) + size2;    /* i equals sum of original sizes */
  48.     if (i > MAXFIELD)
  49.         i = MAXFIELD;    /* a string can't exceed this size */
  50.     if (size2 + size1 > MAXFIELD)
  51.         size2 = MAXFIELD - size1;    /* adjust size2 to not exceed MAXFIELD */
  52.  
  53.     px = p = need(De.ov_ovqpbuf, i);    /* request the needed space */
  54.     bmove(s1->value.sym_data.cptype, p, size1);    /* copy first string */
  55.     p = &p[size1];
  56.     bmove(s2->value.sym_data.cptype, p, size2);
  57.     p = &p[size2];
  58.     s1->value.sym_data.cptype = px;
  59.     s1->len = i;
  60.     /* pad with blanks if necessary */
  61.     i -= size1 - size2;
  62.     while (i--)
  63.         *p++ = ' ';
  64.  
  65. #    ifdef xOTR1
  66.     if (tTf(82, 3))
  67.     {
  68.         printf("Concat:");
  69.         prstack(s1);
  70.     }
  71. #    endif
  72. }
  73. /*
  74. **    Size determines the size of a character symbol
  75. **    without trailing blanks.
  76. */
  77.  
  78. size(s)
  79. register SYMBOL    *s;
  80. {
  81.     register char        *c;
  82.     register int        i;
  83.  
  84.     c = s->value.sym_data.cptype;
  85.     i = s->len & I1MASK;
  86.  
  87.     for (c += i; i; i--)
  88.         if(*--c != ' ')
  89.             break;
  90.  
  91.     return (i);
  92. }
  93. /*
  94. **    Converts the numeric symbol to
  95. **    ascii. Formats to be used are determined
  96. **    by Out_arg.
  97. */
  98.  
  99. ascii(s)
  100. register SYMBOL    *s;
  101. {
  102.     register int        i;
  103.     register char        *p;
  104.     char            temp[MAXFIELD];
  105.     double            dtemp;
  106.     extern struct out_arg    Out_arg;    /* used for float conversions */
  107.     char            *locv();
  108.  
  109.     p = temp;
  110.     switch(s->type)
  111.     {
  112.  
  113.       case INT:
  114.         if (s->len == 4)
  115.         {
  116.             i = Out_arg.i4width;
  117.             p = locv(s->value.sym_data.i4type);
  118.         }
  119.         else
  120.         {
  121.             if (s->len == 2)
  122.             {
  123.                 itoa(s->value.sym_data.i2type, p);
  124.                 i = Out_arg.i2width;
  125.             }
  126.             else
  127.             {
  128.                 itoa(s->value.sym_data.i1type, p);
  129.                 i = Out_arg.i1width;
  130.             }
  131.         }
  132.         break;
  133.  
  134.       case CHAR:
  135.         return;
  136.  
  137.       case FLOAT:
  138.         if (s->len == 4)
  139.         {
  140.             i = Out_arg.f4width;
  141.             dtemp = s->value.sym_data.f4type;
  142.             ftoa(dtemp, p, i, Out_arg.f4prec, Out_arg.f4style);
  143.         }
  144.         else
  145.         {
  146.             i = Out_arg.f8width;
  147.             ftoa(s->value.sym_data.f8type, p, i, Out_arg.f8prec, Out_arg.f8style);
  148.         }
  149.     }
  150.     s->value.sym_data.cptype = need(De.ov_ovqpbuf, i);
  151.     pmove(p, s->value.sym_data.cptype, i, ' ');    /* blank pad to fixed length i */
  152.     s->type = CHAR;
  153.     s->len = i;
  154. }
  155. /*
  156. **    LEXCOMP performs character comparisons between the two
  157. **    strings ss1 and ss2. All blanks and null are ignored in
  158. **    both strings. In addition pattern matching is performed
  159. **    using the "shell syntax". Pattern matching characters
  160. **    are converted to the pattern matching symbols PAT_ANY etc.
  161. **    by the scanner.
  162. **
  163. **    Pattern matching characters can appear in either or
  164. **    both strings. Since they cannot be stored in relations,
  165. **    pattern matching chars in both strings can only happen
  166. **    if the user types in such an expression.
  167. **
  168. **    examples:
  169. **
  170. **    "Smith, Homer" = "Smith,Homer"
  171. **
  172. **    "abcd" < "abcdd"
  173. **
  174. **    "abcd" = "aPAT_ANYd"
  175. **
  176. **    returns    <0 if s1 < s2
  177. **         0 if s1 = s2
  178. **        >0 if s1 > s2
  179. */
  180.  
  181. char    *S1,*S2;
  182. int    L1,L2;
  183.  
  184. lexcomp(s1, l1, s2, l2, x)
  185. register char    *s1, *s2;
  186. register int    l1, l2;
  187. int        x;
  188. {
  189.     char        c1, c2;
  190.     int        howmany = Patnum;    /* howmany PAT_SPEC char matchings so far */
  191.     int         retval;
  192.     int        i;
  193.     char        *t1, *t2;
  194.  
  195. #    ifdef xOTR1
  196.     if (tTf(82, 4))
  197.     {
  198.         printf("LEXCOMP: starting...\n");
  199.         t1 = s1;
  200.         t2 = s2;
  201.         printf("howmany = %d\n", howmany);
  202.         printf("first string= '");
  203.         for (i = 0; i < l1; i++)
  204.             printf("%c", *t1++);
  205.         printf("'\n");
  206.         printf("length = %d\n", l1);
  207.         printf("second string= '");
  208.         for (i = 0; i < l2; i++)
  209.             printf("%c", *t2++);
  210.         printf("'\n");
  211.         printf("length = %d\n", l2);
  212.     }
  213. #    endif
  214.     /* save initial information in case a PAT_GLOB is found */
  215.     if (x==0) 
  216.     {
  217.         S1 = s1; 
  218.         S2 = s2;
  219.         L1 = l1; 
  220.         L2 = l2;
  221.     }
  222. loop:
  223.     while (l1--)
  224.     {
  225.         switch (c1 = *s1++)
  226.         {
  227.  
  228.           /* case ' ': */
  229.           case '\0':
  230.             break;
  231.  
  232.           case PAT_GLOB:
  233.           {
  234.             return(gmatch(S1,L1,S2,L2));
  235.                  }
  236.  
  237.           case PAT_ANY:
  238.             return (pmatch(FALSE, s1, l1, s2, l2));
  239.  
  240.           case PAT_SPEC:
  241.             retval = pmatch(*(s1-1),++s1, --l1, s2, l2);
  242.  
  243.             /*
  244.             ** If there was no match in pmatch, 
  245.             ** reset Patnum to previous value
  246.             */
  247.  
  248. #    ifdef xOTR1
  249.         if (tTf(82,4))
  250.             printf("lexcomp: return %d\n", retval);
  251.  
  252. #    endif
  253.             if (retval) 
  254.                Patnum = howmany;
  255.             return (retval);
  256.  
  257.           case PAT_LBRAC:
  258.             return (lmatch(s1, l1, s2, l2));
  259.  
  260.           default:
  261.             while (l2--)
  262.             {
  263.                 switch (c2 = *s2++)
  264.                 {
  265.  
  266.                   /* case ' ': */
  267.                   case '\0':
  268.                     continue;
  269.  
  270.                   case PAT_GLOB:
  271.                   {
  272.                     return(gmatch(S2,L2,S1,L1));
  273.                   }
  274.  
  275.                   case PAT_ANY:
  276.                     return( pmatch(FALSE,s2,l2,--s1,++l1));
  277.  
  278.                   case PAT_SPEC:
  279.                     retval = pmatch(*(s2-1),++s2, --l2, --s1, ++l1);
  280.  
  281. #    ifdef xOTR1
  282.                     if (tTf(82,4))
  283.                         printf("lexcomp: retval = %d\n", retval);
  284. #     endif
  285.  
  286.                     if (retval) 
  287.                        Patnum = howmany;
  288.                     return (retval);
  289.  
  290.                   case PAT_LBRAC:
  291.                     return (lmatch(s2, l2, --s1, ++l1));
  292.  
  293.                   default:
  294.                     if (c1 == c2)
  295.                         goto loop;
  296.                     if (c1 == PAT_ONE || c2 == PAT_ONE)
  297.                         goto loop;
  298. #    ifdef xOTR1
  299.                     if (tTf(82,4))
  300.                         printf("lexcomp: 2.return %d\n",c1 - c2);
  301. #     endif
  302.                     return (c1 - c2);
  303.                 }
  304.             }
  305. #    ifdef xOTR1
  306.             if (tTf(82,4))
  307.                 printf("lexcomp: returning 1\n");
  308. #    endif
  309.             return (1);    /* s1 > s2 */
  310.         }
  311.     }
  312.  
  313.     /* examine remainder of s2 for any characters */
  314.     while (l2) {
  315.         l2--;
  316.         if ((c1 = *s2++) == PAT_SPEC) 
  317.         {
  318.             pat_insert("",0,*s2,0);  /* insert empty string */
  319.             *s2++,l2--;            /* get rid of index */
  320.         }
  321.         /* if (((c1 = *s2) != ' ') && (c1 != '\0') */
  322.         if ((c1 != ' ') && (c1 != '\0') 
  323.             && (c1 != PAT_ANY) && (c1 != PAT_SPEC))
  324.         {
  325. #    ifdef xOTR1
  326.             if (tTf(82,4))
  327.                 printf("lexcomp: returning -1\n");
  328. #    endif
  329.             Patnum = howmany;
  330.             return (-1);    /* s1 < s2 */
  331.         }
  332.     }
  333. #    ifdef xOTR1
  334.         if (tTf(82,4))
  335.             printf("lexcomp: returning 0\n");
  336. #    endif
  337.     return (0);
  338. }
  339.  
  340.  
  341. /*
  342. **    PMATCH
  343. **
  344. **    Checks if a pattern containing a pattern matching character 
  345. **    (either PAT_ANY or PAT_SPEC) is found in a string.
  346. **
  347. **    Returns:
  348. **         0 -- if pattern found in string
  349. **        -1 -- if no match
  350. **
  351. **    Called By:
  352. **        lexcomp
  353. **
  354. **    Calls:
  355. **        pat_insert, lexcomp
  356. */
  357.  
  358. pmatch(patarg,pat, plen, str, slength)
  359. char     patarg;        /* index for pattern matching--FALSE when no indices 
  360.                 used */
  361. char    *pat;        /* the string holding the pattern matching char */
  362. char    *str;        /* the string to be checked */
  363. int    plen, slength;    /* the lengths */
  364. {
  365.     register char    d, *s;
  366.     register int    slen,count;
  367.     char        c;
  368.  
  369. #    ifdef xOTR1
  370.         if (tTf(82,5))
  371.         {
  372.             printf("PMATCH: starting\n");
  373.             printf("patarg = %c\n",patarg);
  374.             printf("string with pattern char = %s\n", pat);
  375.             printf("string len = %d \n", plen);
  376.             printf("string to check = %s\n", str);
  377.             printf("string len = %d\n", slength);
  378.         }
  379. #    endif
  380.     s = str;
  381.     slen = slength;
  382.  
  383.     if (plen == 0) 
  384.     {
  385.         if ( patarg )
  386.         {
  387.             pat_insert(str,slength,patarg,1);
  388.         }
  389.         return  (0);    /* a match if no more chars in p */
  390.     }
  391.  
  392.     /*
  393.     ** If the next character in "pat" is not another
  394.     ** pattern matching character, then scan until
  395.     ** first matching char and continue comparison.
  396.     */
  397.     if ((c = *pat) != PAT_ANY && c != PAT_SPEC 
  398.         && c != PAT_LBRAC && c != PAT_ONE)
  399.     {
  400.         count = 0;
  401.         while (slen--)
  402.         {
  403.             if ((d = *s) == c || d == PAT_ANY || d == PAT_SPEC 
  404.                 || d == PAT_LBRAC && d != PAT_ONE)
  405.             {
  406.                 if ( patarg )
  407.                 {
  408.                     pat_insert(str,count,patarg,0);
  409.                 }
  410.                 if (lexcomp(s, slen + 1,pat, plen, 1) == 0)
  411.                 {
  412.                     return (0);
  413.                 }
  414.             }
  415.             s++;
  416.             count++;
  417.         }
  418.     }
  419.     else
  420.     {
  421.         while (slen)
  422.         {
  423.             if (lexcomp(s++, slen--,pat, plen, 1) == 0)
  424.                 return (0);    /* match */
  425.         }
  426.     }
  427.     return (-1);    /* no match */
  428. }
  429.  
  430.  
  431. lmatch(pat, plen, str, slen)
  432. char    *pat;    /* the string holding the pattern matching char */
  433. char    *str;    /* the other string */
  434. int    plen, slen;    /* their respective sizes */
  435. {
  436.     register char    *p, *s;
  437.     register int    cc;
  438.     int        oldc, c, found;
  439.  
  440. #    ifdef xOTR1
  441.         if (tTf(82,6))
  442.         {
  443.             printf("LMATCH: starting...\n");
  444.             printf("Pat = %s, length = %d\n", pat, plen);
  445.             printf("Str = %s, length = %d\n", str, slen);
  446.         }
  447. #    endif
  448.     p = pat;
  449.     s = str;
  450.  
  451.     /* find a non-blank, non-null char in s */
  452.     while (slen--)
  453.     {
  454.         if ((c = *s++) != ' ' && c != '\0')
  455.         {
  456.             /* search for a match on 'c' */
  457.             found = 0;    /* assume failure */
  458.             oldc = 0777;    /* make previous char large */
  459.  
  460.             while (plen--)
  461.             {
  462.  
  463.                 switch(cc = *p++)
  464.                 {
  465.  
  466.                   case PAT_RBRAC:
  467.                     if (found)
  468.                     {
  469.                         return (lexcomp(s, slen,p, plen, 1));
  470.                     }
  471.                     return (-1);
  472.  
  473.                   case '-':
  474.                     if (plen-- == 0)
  475.                         return (-1);    /* not found */
  476.                     if (oldc <= c && c <= (cc = *p++))
  477.                         found++;
  478.                     break;
  479.  
  480.                   default:
  481.                     if (c == (oldc = cc))
  482.                         found++;
  483.                 }
  484.             }
  485.             return (-1);    /* no match */
  486.         }
  487.     }
  488.     return (1);
  489. }
  490.  
  491.  
  492.  
  493. /*
  494. **    GMATCH: checks for string matches while grabbing all instances
  495. **        of the string delimited by PAT_GLOB.
  496. **
  497. */
  498.  
  499. gmatch(s1,l1,s2,l2)
  500. register char     *s1,*s2;
  501. register int    l1,l2;
  502. {
  503.     char    *start,*end,*pat,*c,*temps2;
  504.     int    slen=0,elen=0,plen=0;
  505.     int    index,stindex,endex;
  506.     int    retval,templ2,smlen,first;
  507.     GLIST    *g;
  508.  
  509. #    ifdef xOTR1
  510.         if (tTf(82,7))
  511.         {
  512.             printf("GMATCH: s1 = %s\n", s1);
  513.             printf("GMATCH: l1 = %d\n", l1);
  514.             printf("GMATCH: s2= %s\n", s2);
  515.             printf("GMATCH: l2 = %d\n", l2);
  516.         }
  517. #    endif
  518.     c = s2;
  519.     for (c += l2; l2; l2--)
  520.         if(*--c != ' ')
  521.             break;
  522.     c = s1;
  523.     for (c += l1; l1; l1--)
  524.         if(*--c != ' ')
  525.             break;
  526.  
  527.     if (*s1 == PAT_SPEC)
  528.     {
  529.         s1 += 2;
  530.         l1 -= 2;
  531.     }
  532.     else if (*s1 == PAT_ANY)
  533.     {
  534.         s1++;
  535.         l1--;
  536.     }
  537.     c = (start = need(De.ov_ovqpbuf, l1));
  538.     while (l1-- && PAT_GLOB != *s1++) {
  539.         *c++ = *(s1-1);
  540.         slen++;
  541.     }
  542.     c = (pat = need(De.ov_ovqpbuf, l1));
  543.     while ( l1-- && *s1++ != PAT_GLOB) {
  544.         *c++ = *(s1-1);
  545.         plen++;
  546.     }
  547.     end = s1;
  548.     elen = l1;
  549.  
  550.     if (slen != elen && (!slen || !elen))
  551.     {
  552.         return(-1);
  553.     }
  554.  
  555.     Globs = NULL;
  556.     if (!slen) 
  557.     {
  558.         index = scanstr(s2,l2,pat,plen,1,1);
  559.         if (index == -1) 
  560.         {
  561.         return(-1);
  562.         }
  563.         add_glob(s2,index);
  564.         for (;;) {            /* this loop ends when index is -1 */
  565.         s2 += index + plen;
  566.         l2 -= index + plen;
  567.         index = scanstr(s2, l2,pat,plen,1,1);
  568.         if (index == -1)
  569.         {    /* since string is finite, guaranteed to happen */
  570.             add_glob(s2,l2);
  571.             Globfoot->next = NULL;
  572.             return(0);
  573.         }
  574.         add_glob(s2,index);
  575.         }
  576.     }
  577.     else {
  578.         retval = 1;
  579.         first = 0;
  580.         temps2 = s2;
  581.         templ2 = 0;
  582.         for(;;) {
  583.         if (first) {
  584.             s2 += smlen + elen;
  585.             l2 -= smlen + elen;
  586.             templ2 += smlen + elen;
  587.         }
  588.         else
  589.             first = 1;
  590.         if ((stindex=scanstr(s2,l2,start,slen,1,1)) == -1 ||
  591.             (endex = scanstr(s2+stindex+slen,l2-stindex-slen,end,elen,1,1)) == -1)
  592.             {
  593.             if (!retval) 
  594.             {
  595.                 templ2 += l2;
  596.                 add_glob(temps2,templ2);
  597.             }
  598.             return(retval);
  599.             }
  600.         s2 += stindex + slen;
  601.         l2 -= stindex + slen;
  602.         templ2 += stindex + slen;
  603.         smlen = endex;
  604.         for (;(index = scanstr(s2,smlen,pat,plen,1,1)) != -1;)
  605.         {
  606.             retval = 0;
  607.             templ2 += index;
  608.             add_glob(temps2,templ2);
  609.             temps2 += templ2 + plen;
  610.             templ2 = 0;
  611.             s2 += index + plen;
  612.             l2 -= index + plen;
  613.             smlen -= index + plen;
  614.         }
  615.         }
  616.     }
  617.             
  618. }
  619.  
  620.  
  621. add_glob(str,slen)
  622. char    *str;
  623. int    slen;
  624. {
  625.   char  *malloc();
  626. #    ifdef xOTR1
  627.         if (tTf(82,8))
  628.             printf("ADD_GLOB: str = %s, slen = %d\n", str, slen);
  629. #    endif
  630.         if (Globs == NULL) {
  631.         Globs =
  632.           (Globfoot = (GLIST *) malloc(sizeof(GLIST)));
  633.         Globs->string = malloc(slen);
  634.         bmove(str,Globs->string,slen);
  635.         Globlen = Globs->len = slen;
  636.         Globnum = 1;
  637.         }
  638.         else {
  639.         Globfoot->next = (GLIST *) malloc(sizeof(GLIST));
  640.         Globfoot = Globfoot->next;
  641.         Globfoot->string = malloc(slen);
  642.         bmove(str,Globfoot->string,slen);
  643.         Globlen += (Globfoot->len = slen);
  644.         Globnum++;
  645.         }
  646.  
  647. }
  648.  
  649. /*
  650. **    PAT_INSERT 
  651. **    
  652. **    Moves str and its corresponding length into Pats[index] 
  653. **    where index refers to the PAT_SPEC index.
  654. **
  655. **    May be called even though the Pats[index] string is not the one 
  656. **    which will eventually be used for the replace.  For instance, 
  657. **    if the pattern matching coincides but the line number doesn't.
  658. **
  659. **    Side Effects:
  660. **        Patnum is incremented indicating an insertion was done.
  661. **        Pats[index] record gets a new string and length.
  662. **
  663. **    Returns:  none
  664. **
  665. **    Calls:    bmove
  666. **
  667. **    Called By:
  668. **        pmatch, lexcomp
  669. */
  670.  
  671. pat_insert(str,slen,where,no_blanks)
  672. char     *str;        /* the string being moved to Pats[where] */
  673. int     slen;        /* length of str */
  674. char     where;        /* index into Pats */
  675. int    no_blanks;
  676. {
  677.     int    index;        /* integer value of Pats' index */
  678.     int     i;
  679.     char    *malloc();
  680.  
  681.     index = where - '0';
  682.     if (no_blanks)        /* get rid of blanks */
  683.         while (*(str + slen - 1) == ' ')  
  684.         slen--;
  685.  
  686.     if (Pats[index].string)         /* for overwriting string */
  687.     {
  688.         free(Pats[index].string);
  689.         Pats[index].string = NULL;    /* Not really necessary, but helps with debugging */
  690.     }
  691.         Patnum++;
  692.  
  693.     Pats[index].string = malloc(slen);
  694.     bmove(str,Pats[index].string,slen);    /* move str to Pats[].string */
  695.     Pats[index].len = slen;
  696. #    ifdef xOTR1
  697.         if (tTf(82,9))
  698.         {
  699.             for (i = 0; i < PATNUM; i++)
  700.                 printf("Pats[%d] = %s, len = %d\n", i,Pats[i].string, Pats[i].len);
  701.         }
  702. #    endif
  703.  
  704. }
  705.  
  706.  
  707. /*
  708. **
  709. **    INSERT_CHARS replaces all [PAT_SPEC, index] pairs with strings from 
  710. **    the Pats[] array.  The PAT_SPEC index corresponds to the index into
  711. **    the Pats[] array.
  712. **
  713. **    Calls:    bmove
  714. **
  715. **    Called by:  interpret
  716. **
  717. **    Returns:  none    
  718. */
  719.  
  720. insert_chars(op)
  721. SYMBOL *op;
  722. {
  723.     char     *st, *s,    /* pointers to SYMBOL string */
  724.         *new;        /* pointer to new string being formed */
  725.     int     l,        /* length of SYMBOL string */
  726.         size = 0;    /* size of new string being formed */
  727.     int        tot,        /* total size of new string being formed */
  728.         index,        /* PAT_SPEC index */
  729.         flag=0;
  730.  
  731. #    ifdef xOTR1
  732.         if (tTf(82,10))
  733.             printf("INSERT_CHARS: starting...\n");
  734. #    endif
  735.     l = op->len & I1MASK;
  736.     st = s = op->value.sym_data.cptype; 
  737.     while (*(s+l-1) == ' ')
  738.     l--;                /* don't worry about blanks */
  739.     tot = l;
  740.     while (l--) {
  741.     if (*st == PAT_GLOB)
  742.     {
  743.         insert_glob(&s,++st,&tot,l);
  744.         break;
  745.     }
  746.     if (*st++ == PAT_SPEC) {
  747.         index = *st++ - '0';
  748.         l--;
  749.  
  750.         /* subtract 2 for PAT_SPEC and corresponding index */
  751.         tot += Pats[index].len - 2;
  752.  
  753.         new = need(De.ov_ovqpbuf, tot);
  754.         if (size)
  755.             bmove(s,new,size);
  756.  
  757.         /* append the Pats[] string to the currently forming string */
  758.         bmove(Pats[index].string,new+size,Pats[index].len);
  759.  
  760.         if (!flag)
  761.             flag = 1;
  762.         else
  763.             free(s);
  764.         s = new;  
  765.         size += Pats[index].len;
  766.         if (l) {
  767.             bmove(st,new+size,l);
  768.             st = new + size;
  769.         }    
  770.     }
  771.     else 
  772.         size++;
  773.     } /* while */
  774.  
  775.     /*
  776.     **  replace SYMBOL string with
  777.     **  new string and length
  778.     */
  779.     op->value.sym_data.cptype = s;
  780.     op->len = tot;
  781. }
  782.  
  783.  
  784. insert_glob(start,rest,slen,rlen)
  785. char    **start,*rest;
  786. int    *slen,rlen;
  787.     char    *pat = rest,*new;
  788.     int    plen = 0,newlen,i;
  789.     GLIST    *g;    
  790.  
  791.     while (rlen-- && *rest++ != PAT_GLOB)
  792.         plen++;
  793.     /* put in error checking about 2nd PAT_GLOB */
  794.     *slen -= plen + 2 + rlen;
  795.     newlen = *slen + rlen + Globlen + (Globnum-1)*plen;
  796.     new = need(De.ov_ovqpbuf, newlen);
  797.     bmove(*start,new,*slen);
  798.     *start = new;
  799.     new += *slen;
  800.     for (i = Globnum,g=Globs;i>1;i--,g=g->next) {
  801.         bmove(g->string,new,g->len);
  802.         new += g->len;
  803.         bmove(pat,new,plen);
  804.         new += plen;
  805.     }
  806.     bmove(g->string,new,g->len);
  807.     new += g->len;
  808.     bmove(rest,new,rlen);
  809.     *slen = newlen;
  810. }
  811.  
  812.  
  813.  
  814. int flink[MAXFIELD];          /* array for storing failure points in string */
  815.  
  816. newstring(op1,op2)
  817. register SYMBOL    *op1,*op2;
  818. {
  819.     int    stsize,psize,index,index2;
  820.  
  821.     psize = op2->len & I1MASK;    /* ignore trailing blanks */
  822.     stsize = op1->len & I1MASK;
  823.     if (op2->start != -1)
  824.     {
  825.         index = op2->start;
  826.     }
  827.     else
  828.         index = scanstr(op1->value.sym_data.cptype,stsize,
  829.                 op2->value.sym_data.cptype,psize,
  830.                 CLOSED,(char) 1);    /* get start of string */    
  831.     if (index != -1) {
  832.         index2 = index + psize;
  833.         bmove(op1->value.sym_data.cptype + index2,
  834.               op1->value.sym_data.cptype + index, stsize - index2);
  835.         for (index += stsize - index2; index < stsize; index++)
  836.               *(op1->value.sym_data.cptype + index) = ' ';
  837.     }
  838. }
  839.  
  840.         
  841.  
  842. createlink(pat,plen)
  843. char    *pat;
  844. int    plen;
  845. {
  846.     int i,j;
  847.  
  848.     flink[0] = -1;
  849.     i = 1;
  850.     while (i < plen) 
  851.     {
  852.     j = flink[i-1];
  853.     while (j != -1 && pat[j] != pat[i-1])
  854.         j = flink[j];
  855.     flink[i] = j + 1;
  856.     i += 1;
  857.     }
  858. }
  859.  
  860.  
  861. backlink(pat,plen)
  862. char    *pat;
  863. int    plen;
  864. {
  865.     int i,j;
  866.  
  867.     flink[plen - 1] = plen;
  868.     i = plen - 2;
  869.     while (i >= 0) 
  870.     {
  871.     j = flink[i+1];
  872.     while (j != plen && pat[j] != pat[i+1])
  873.         j = flink[j];
  874.     flink[i] = j - 1;
  875.     i -= 1;
  876.     }
  877. }
  878.  
  879.  
  880.  
  881. /*
  882. **    SCANSTR:  Scan a string for a pattern.  
  883. **
  884. **    Returns:
  885. **        -1 -- couldn't find pattern in string
  886. **        index in string to start of pattern -- if getstart is true
  887. **        index in string following pattern   -- if getstart is false
  888. */
  889.  
  890. scanstr(str,slen,pat,plen,getstart,num)
  891. char    *str,        /* string being scanned                  */
  892.     *pat;        /* pattern being searched for                  */
  893. int    slen,        /* str length                         */
  894.     plen;        /* pat length                         */
  895. int     getstart;    /* if true, include pat in the string to be returned */
  896. char    num;        /* number of occurance to look for             */
  897. {
  898.     int i,    /* index into str */
  899.     j,    /* index into pat */
  900.     k,
  901.     found;    /* true when pattern found in string */
  902.  
  903. # ifdef xOTR1
  904.     if (tTf(82,11))
  905.     {
  906.         printf("SCANSTR: \n");
  907.         printf("str = %s, len = %d\n", str, slen);
  908.         printf("pat = %s, len = %d\n", pat, plen);
  909.     }
  910. # endif
  911.  
  912.     createlink(pat,plen);
  913.     i = -1;
  914.  
  915.     /* for each occurance of pattern in string */
  916.     for (k = 0; k < (num & I1MASK); k++) {
  917.     i += 1;
  918.     j = 0;
  919.     found = 0;
  920.     while (i < slen) {
  921.  
  922.         /* keep searching str until a potential match for pat is found */
  923.         while ( j != -1 && pat[j] != str[i])
  924.         j = flink[j];
  925.  
  926.         if (j == plen-1)     /* found pat in str */
  927.         {
  928.         found = 1;
  929.         break;
  930.         }
  931.         else {        /* else check that rest of pat matches */
  932.         i += 1;
  933.         j += 1;
  934.         }
  935.     }
  936.     if (!found || i == slen) return(-1);    /* didn't find pat in str */
  937.     }
  938.  
  939.     /** at this point, found pattern in string **/
  940.     if (getstart)
  941.     {
  942.     return(i-plen+1);
  943.     }
  944.     else 
  945.     {
  946.     return(i+1);
  947.     }
  948. } /* scanstr */
  949.  
  950. /*
  951. **    BACKSCAN
  952. **
  953. **    Searches backwards through string for pattern.
  954. **
  955. **    Returns:
  956. **        -1 -- if pattern not found
  957. **        index in string where pattern starts -- if getstart is true
  958. **        index in string right after pattern ends -- if getstart is false
  959. */
  960.  
  961. backscan(str,slen,pat,plen,getstart,num)
  962. char    *str,        /* string being scanned             */
  963.     *pat;        /* pattern being searched for             */
  964. int    slen,        /* length of string                */
  965.     plen;        /* length of pattern                */
  966. int     getstart;    /* if true, return pointer which includes pat    */
  967.             /* if false, return pointer following pat    */
  968. char     num;        /* which occurance of pat in string        */
  969. {
  970.     int i,        /* index into string           */
  971.     j,        /* index into pat and flink       */
  972.     k,        /* number of occurance found       */
  973.     found;        /* true if pattern found in string */
  974.  
  975. # ifdef xOTR1
  976.     if (tTf(82,12))
  977.     {
  978.         printf("BACKSCAN: \n");
  979.         printf("str = %s, len = %d\n", str, slen);
  980.         printf("pat = %s, len = %d\n", pat, plen);
  981.     }
  982. # endif
  983.     backlink(pat,plen);        /* set up flink for backwards scanning */
  984.     i = slen ;
  985.  
  986.     /* for each occurance of pat in string */
  987.     for (k = 0; k < (num & I1MASK); k++) {
  988.     i -= 1;
  989.     j = plen - 1;
  990.     found = 0;
  991.  
  992.     /* search for pat from end of string until whole string is examined */
  993.     while (i >= 0) {
  994.         while ( j != plen && pat[j] != str[i])
  995.         j = flink[j];
  996.         if (j == 0)  {
  997.         found = 1;
  998.         break;
  999.         }    
  1000.         else {
  1001.         i -= 1;
  1002.         j -= 1;
  1003.         }
  1004.     }
  1005.     if (!found || i < 0) return(-1);
  1006.     }
  1007.     /* return pointers to pattern in string */
  1008.     if (getstart)
  1009.     {
  1010.     return(i);
  1011.     }
  1012.     else 
  1013.     {
  1014.     return(i+plen);
  1015.     }
  1016. } /* backscan */
  1017.  
  1018. getend(len,dropend,howmany)
  1019. int    len,dropend,howmany;
  1020. {
  1021.     int i;
  1022.  
  1023.     for (i = 0;i < (howmany & I1MASK); i++)
  1024.         len--;
  1025.     if (dropend)
  1026.         len--;
  1027.     return(len);
  1028. }
  1029.  
  1030. /*
  1031. **    GRABSTRING grabs a string described by a pattern matching 
  1032. **    interval in a query.
  1033. **
  1034. **    Called by:  getsymbol
  1035. **
  1036. **    Calls:    scanstr, backscan, getend, specdelim
  1037. **
  1038. **    Returns:
  1039. **        NULL -- if pattern was not found in string
  1040. **        ptr to pattern which matches interval -- otherwise
  1041. */
  1042.  
  1043. char *
  1044. grabstring(strinfo,str,len,startptr)
  1045. STRKEEPER    *strinfo;        /* info about delimitors */
  1046. char        *str;            /* string to search */
  1047. int        *len;            /* length of string */
  1048. int        *startptr;
  1049. {
  1050.     int     start=0,end=0;        /* start and end of substring */
  1051.     int    done = 0;        
  1052.     char    *s;
  1053.     char     leftint, rightint;    /* type of interval */
  1054.     char     leftnum, rightnum;    /* number of occurrence to find */
  1055.     char     leftspec, rightspec;    /* special chars 1= special delim */
  1056.                     /* 2 = search backwards */
  1057.     char    *leftpat, *rightpat;    /* left and right patterns */
  1058.     int    stsearch;        /* where to start searching 2nd time */
  1059.     int    leftlen, rightlen;    /* lengths of patterns returned from specdelim*/
  1060.  
  1061.     /* initialization */
  1062.     leftint = strinfo->type[0];
  1063.     rightint = strinfo->type[1];
  1064.     leftnum = strinfo->number[0];
  1065.     rightnum = strinfo->number[1];
  1066.     leftspec = strinfo->flag[0];
  1067.     rightspec = strinfo->flag[1];
  1068.     leftpat = strinfo->string[0];
  1069.     rightpat = strinfo->string[1];
  1070.  
  1071.     *len &= I1MASK;            /* only look at lower byte */
  1072.  
  1073.     while (*(str+*len-1) == ' ')    /* find last nonblank char of string */
  1074.         *len -= 1;
  1075.  
  1076. # ifdef xOTR1
  1077.     if (tTf(82,1))
  1078.     {
  1079.         printf("GRABSTRING:\n");
  1080.         printf("str = %s, len = %d\n", str, *len);
  1081.         printf("leftint = %d, leftnum = %d, leftspec = %d\n", leftint, leftnum, leftspec);
  1082.         printf("left pattern = %s, len = %d\n", leftpat, strlen(leftpat));
  1083.         if (rightpat) {
  1084.           printf("rightint = %d, rightnum = %d, rightspec = %d\n", rightint, rightnum, rightspec);
  1085.           printf("right pattern = %s, len = %d\n", rightpat, strlen(rightpat));
  1086.         }
  1087.     }
  1088. # endif
  1089.  
  1090.     /* search for left endpoint */
  1091.  
  1092.     /* CASE 1: special chars */
  1093.     if (leftspec & 1)
  1094.     {
  1095.             start = specdelim(str,*len,leftpat,leftint,leftnum,&leftlen);
  1096.         if (leftint == CLOSED)
  1097.             stsearch = start + leftlen;
  1098.         else
  1099.         {
  1100.             start += leftlen;
  1101.             stsearch = start;
  1102.         }
  1103.     }
  1104.     /* CASE 2: backwards searching */
  1105.     else if (leftspec & 2)
  1106.     {
  1107.             if (leftpat == NULL)
  1108.             start = 1 + getend(*len,leftint,leftnum);
  1109.             else
  1110.             start = backscan(str , *len, leftpat, 
  1111.                      strlen(leftpat),leftint,leftnum);
  1112.         if (leftint == CLOSED)
  1113.             stsearch = start + strlen(leftpat);
  1114.         else
  1115.             stsearch = start;
  1116.     }
  1117.     /* CASE 3: forwards searching */
  1118.     else                    
  1119.     {
  1120.             start = scanstr(str + start, *len, leftpat, 
  1121.                     strlen(leftpat),leftint,leftnum);
  1122.         if (leftint == CLOSED)
  1123.             stsearch = start + strlen(leftpat);
  1124.         else
  1125.             stsearch = start;
  1126.     }
  1127.  
  1128.  
  1129.  
  1130.     if (start == -1)        /* if pattern was not found in str */
  1131.     {
  1132.         return(NULL);
  1133.     }
  1134.  
  1135.     /* search for right endpoint */
  1136.  
  1137.     /* CASE 1: special chars */
  1138.     else if (rightspec & 1)
  1139.     {
  1140.         if ((end = specdelim(str + stsearch,*len - stsearch,
  1141.                       rightpat, 1 - rightint, rightnum,
  1142.                       &rightlen)) == -1)
  1143.             return(NULL);
  1144.         else
  1145.         {
  1146.             if (rightint == CLOSED)
  1147.                 end += stsearch + rightlen;
  1148.             else
  1149.                 end += stsearch;
  1150.         }
  1151.     }
  1152.     /* Backwards searching */
  1153.     else if (rightspec & 2)
  1154.     {
  1155.       if (rightpat == NULL)
  1156.         end = *len;
  1157.       else
  1158.         end = backscan(str, *len, rightpat, strlen(rightpat),1 - rightint,
  1159.                rightnum);
  1160.     }
  1161.     /* Forwards searching */
  1162.     else
  1163.     {
  1164.       if (rightpat == NULL)
  1165.         end = stsearch;
  1166.       else
  1167.         if ((end = scanstr(str + stsearch, *len,rightpat, 
  1168.                    strlen(rightpat),1 - rightint,
  1169.                    rightnum)) == -1)
  1170.           return(NULL);
  1171.         else
  1172.           {
  1173.         end += stsearch;
  1174.           }
  1175.     }
  1176.  
  1177.     
  1178.     if (end == -1 || end - start <= 0)    /* if end of interval couldn't 
  1179.                         ** be found or end did not come 
  1180.                         ** after start */
  1181.     {
  1182.         return(NULL);
  1183.     }
  1184.     else
  1185.     {    
  1186.         *len = end - start;
  1187.         s = need(De.ov_ovqpbuf, *len);
  1188.         bmove (str + start, s, *len);
  1189.         *startptr = start;
  1190.     }
  1191.  
  1192.  
  1193.     return(s);
  1194. } /* grabstring */
  1195.  
  1196. /*
  1197. **    SPECDELIM -- scan a string for a pattern specified by a special
  1198. **        delimiter 
  1199. **
  1200. **        Parameters:
  1201. **            str - string to be scanned
  1202. **            slen - length of string
  1203. **            dname - name of delimitor
  1204. **            getstart - type of interval
  1205. **            num - occurrence of pattern to look for
  1206. **
  1207. **        Returns:
  1208. **            index into string of pattern
  1209. **            -1 if pattern not found
  1210. **            -2 if delimitor was never defined
  1211. **
  1212. **        Called by:
  1213. **            grabstring
  1214. **
  1215. */
  1216. specdelim(str, slen, dname, getstart, num, plen)
  1217. char    *str;
  1218. int    slen;
  1219. char    *dname;
  1220. int    getstart;
  1221. char    num;
  1222. int    *plen;
  1223. {
  1224.     extern DELIMLIST    *Delimhead;    /* ptr to queue of delims */
  1225.     DELIMLIST        *d;
  1226.     DMAP            *map;        /* ptr to bitmap */
  1227.     char            patch;
  1228.     int            start = -1;    /* index to start of pattern */
  1229.     int            match;        /* true while a pattern is matching */
  1230.     char            *savestr;
  1231.     int            savelen;
  1232.     int            k;
  1233.     int            i;
  1234.  
  1235.  
  1236. # ifdef xOTR1
  1237.     if (tTf(82,2))
  1238.     {
  1239.         printf("SPECDELIM: starting...\n");
  1240.         printf("str = %s\n",str);
  1241.         printf("slen = %d\n",slen);
  1242.         printf("delim = %s\n",dname);
  1243.     }
  1244. # endif
  1245.  
  1246.     savestr = str;
  1247.     savelen = slen;
  1248.     *plen = 0;
  1249.     /* find correct delimiter in the queue */
  1250.     for (d = Delimhead; d != NULL && strcmp(d->delim,dname);d = d->back)
  1251.         continue;
  1252.  
  1253.     if (d == NULL)
  1254.     {
  1255.         ov_err(BADDELIM);
  1256.     }
  1257.  
  1258.     for (k = 0; k < (num & I1MASK); k++)
  1259.     {
  1260.         if (k)
  1261.         {
  1262.             start = start - 1 + *plen;
  1263.         /*     savestr = &savestr[start]; */
  1264.  
  1265.             for ( i = 0; i < *plen - 1; i++)
  1266.             {
  1267.                 *savestr++;
  1268.                 savelen--;
  1269.             }
  1270.  
  1271.         }
  1272.         while (savelen > 0)
  1273.         {
  1274.             map = d->maptr;
  1275.             start++;
  1276.             *plen = 0;
  1277.             str = savestr;
  1278.             slen = savelen;
  1279.             savestr++;
  1280.             savelen--;
  1281.             patch = *str++;
  1282.             match = TRUE;
  1283.     
  1284.             while ((map != NULL) && (slen >= 0) && (match))
  1285.             {
  1286.                 switch (map->type)
  1287.                 {
  1288.                     case ONE:
  1289.                     if (test(map->bits, patch))
  1290.                     {
  1291.                         map = map->next;
  1292.                         patch = *str++;
  1293.                         slen--;
  1294.                         (*plen)++;
  1295.                     }
  1296.                     else
  1297.                         match = FALSE;
  1298.                     break;
  1299.     
  1300.                     case ZEROMORE:
  1301.                     while((slen >= 0) && (test(map->bits,patch)))
  1302.                     {
  1303.                         patch = *str++;
  1304.                         slen--;
  1305.                         (*plen)++;
  1306.                     }
  1307.                     map = map->next;
  1308.                     break;
  1309.                 }
  1310.             }
  1311.     
  1312.             if ((map == NULL))
  1313.             {
  1314.                 /* pattern was found */
  1315.                 break;
  1316.             }
  1317.         }
  1318.         if ((slen <= 1) && (map != NULL))
  1319.             return(-1);
  1320.     }
  1321.     return(start);
  1322. }
  1323.